package dhadi.model;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

public class WeightedList<K> {

    private Map<K, Double> weightedList = new HashMap<K,Double>();

    public void add(K object) {
        Double o = weightedList.get(object);
        if (o != null) {
            weightedList.put(object, new Double(o.intValue()+1));
        } else {
            weightedList.put(object, new Double(1));
        }
    }
    
    /**
     * Adds given weightedList into this weighted list, 
     * each item is added with the given weight plus
     * each individual weight in weightedList
     * 
     * @param bestBlockingMoves
     * @param weight
     */
    public void add(WeightedList<K> weightedList, double weight) {
        for (Entry<K, Double> entry : weightedList.weightedList.entrySet()) {
            this.add(entry.getKey(), entry.getValue() + weight);
        }
    }

    public void add(K object, Double weight) {
        Double o = weightedList.get(object);
        if (o != null) {
            weightedList.put(object, new Double(o.intValue()+weight));
        } else {
            weightedList.put(object, weight);
        }
    }
    
    public void add(List<K> objects, Double weight) {
        for (K object : objects) {
            this.add(object, weight);
        }
    }

    public boolean isEmpty() {
        return this.weightedList.isEmpty();
    }

    public K getHeavyWeight() {
        return mGetHeavyWeight(weightedList.entrySet());        
    }
    
    /**
     * Returns heavy weitht object other the objects
     * specified in excludeList
     * @param exclude
     * @return
     */
    public K getHeavyWeight(List<K> excludeList) {
        Set<Entry<K, Double>> reminder = new HashSet<Entry<K, Double>>();  
        for (Entry<K, Double> entry : weightedList.entrySet()) {
            if (!excludeList.contains(entry.getKey())) {
                reminder.add(entry);
            }
        }
        return mGetHeavyWeight(reminder);
    }
    
    private K mGetHeavyWeight(Set<Entry<K, Double>> weightedList) {
        double maxWeight = -Double.MAX_VALUE;
        Entry<K,Double> maxEntry = null; 
        for (Entry<K, Double> entry : weightedList) {
            if (maxWeight < entry.getValue().doubleValue()) {
                maxWeight = entry.getValue().doubleValue();
                maxEntry = entry;
            }
        }
        if (maxEntry != null) return maxEntry.getKey();
        else return null;
    }
    
    public K getLightWeight() {

        double minWeight = Double.MAX_VALUE;
        Entry<K,Double> minEntry = null; 
        for (Entry<K, Double> entry : weightedList.entrySet()) {
            if (minWeight > entry.getValue().doubleValue()) {
                minWeight = entry.getValue().doubleValue();
                minEntry = entry;
            }
        }
        if (minEntry != null) return minEntry.getKey();
        else return null;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (Entry<K, Double> entry : weightedList.entrySet()) {
            sb.append(entry.getKey()).append("(").append(entry.getValue().intValue())
            .append(")").append(" ");
        }
        return sb.toString();
    }
}